import fs from "fs";
import axios from 'axios';
import {expect} from 'chai';
import sinon from 'sinon';
// @ts-ignore
import {GetEndpoint, CACHE_TYPE_OSS, init} from '../src/cache';
import {IParams} from '../src/params';

export function mockIParams(): IParams {
    let iParams = new IParams();
    iParams.cacheType = CACHE_TYPE_OSS;
    iParams.pipelineID = 123456;
    iParams.projectDir = '/tmp';
    iParams.pipelineName = 'pipelineName';
    iParams.buildJobID = 123456;
    iParams.engineTaskSign = 'engineTaskSign';
    iParams.fileParentID = 'fileParentID';
    iParams.fileID = 'fileID';
    iParams.archivePath = '/tmp/archive.zip';
    iParams.bucketName = 'bucketName';
    iParams.endpoint = 'endpoint';
    iParams.workspace = 'workspace';
    iParams.accessKeyID = 'accessKeyID';
    iParams.accessKeySecret = 'accessKeySecret';
    iParams.command = 'command';
    iParams.operator = 'employeeID';
    iParams.pluginDir = 'pluginDir';
    iParams.securityToken = 'securityToken';
    iParams.buildNumber = 123456;
    iParams.cacheName = 'cacheName';
    return iParams;
}

let sandbox = sinon.createSandbox()
let mockFsRmSync: sinon.SinonStub;
let mockFsMkdirSync: sinon.SinonStub;
let mockAxiosGet: sinon.SinonStub;

beforeEach(() => {
    mockFsRmSync = sandbox.stub(fs, 'rmSync');
    mockFsMkdirSync = sandbox.stub(fs, 'mkdirSync');
    mockAxiosGet = sandbox.stub(axios, 'get')
})

afterEach(() => {
    sandbox.restore();
});

describe('GetEndpoint', () => {
    it('should return the provided endpoint if present in params', async () => {
        const customEndpoint = 'custom.oss.aliyuncs.com';
        const params: IParams = mockIParams()
        params.endpoint = customEndpoint

        const result = await GetEndpoint(params);
        expect(result).to.equal(customEndpoint);
    });

    it('should resolve to oss-cn-beijing-internal.aliyuncs.com when successful request to the internal endpoint', async () => {
        const stub = mockAxiosGet.resolves({status: 200});
        const params: IParams = mockIParams()
        params.endpoint = ""
        params.cacheType = CACHE_TYPE_OSS;

        const result = await GetEndpoint(params);
        expect(stub.calledOnceWithExactly('https://oss-cn-beijing-internal.aliyuncs.com', {timeout: 1000})).to.be.true;
        expect(result).to.equal('oss-cn-beijing-internal.aliyuncs.com');
    });

    it('should resolve to oss-accelerate.aliyuncs.com when the request to the internal endpoint fails', async () => {
        const error = new Error('Request failed');
        const stub = mockAxiosGet.rejects(error);
        const params: IParams = mockIParams()
        params.endpoint = ""
        params.cacheType = CACHE_TYPE_OSS;

        const result = await GetEndpoint(params);
        expect(stub.calledOnceWithExactly('https://oss-cn-beijing-internal.aliyuncs.com', {timeout: 1000})).to.be.true;
        expect(result).to.equal('oss-accelerate.aliyuncs.com');
    });
});

describe('init', () => {
    it('should initialize the parameters and return artifactFullName', async () => {
        const params = mockIParams()
        params.fileID = '/path/to/file'
        params.cacheName = 'test-cache';
        params.engineTaskSign = 'task-sign';
        params.workspace = '/tmp/workspace/path';
        params.archivePath = '$WORK_SPACE/cache/*.tgz';

        const expectedArtifactFullName = `${params.workspace}/packages/test-cache-task-sign.tgz`;
        const result = init(params);

        expect(mockFsRmSync.calledWithExactly(`${params.workspace}/packages`, {recursive: true, force: true})).to.be.true;
        expect(mockFsMkdirSync.calledWithExactly(`${params.workspace}/packages`, {recursive: true})).to.be.true;
        expect(result).to.equal(expectedArtifactFullName);
    });
});